import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.*;
import static org.junit.Assert.fail;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Semaphore;

import model.EErrorPopUp;
import model.cnf.CNF;
import model.cnf.FileCNF;
import model.cnf.Stat;
import model.preprocessor.PreProcessorFactory;
import model.session.CNFUse;
import model.session.ExecutableSessionBlock;
import model.session.SessionBlock;
import model.solver.SolverFactory;

import org.junit.Before;
import org.junit.Test;

import vue.IIG;
import vue.IIGSessionManager;
import controller.Controller;
import controller.IController;
import controller.ISessionManager;
import controller.SessionManager;

/**
 * 
 */

/**
 * @author GRONOWSKI Stephane svan001@aol.com
 * 
 *         igsat 2010
 * 
 */
public class TestController {

	private String				cnflonguepath	= "./tstcnf/longue.cnf";
	private String				cnfsatpath		= "./tstcnf/sat.cnf";
	private String				cnfunsatpath	= "./tstcnf/unsat.cnf";
	private String				cnfcourpath		= "./tstcnf/cour.cnf";
	private String				cnfcourtepath	= "./tstcnf/courte.cnf";
	private String				out				= "./cnf/newcnf.cnf";
	private String				out2			= "./cnf/newcnf2.cnf";


	private File				dirpreproc		= new File("./preproc");
	private File				dirsolveur		= new File("./solveur");

	private PreProcessorFactory	preprocfactory	= new PreProcessorFactory(dirpreproc);
	private SolverFactory		solverfactory	= new SolverFactory(dirsolveur);

	IG							ig;
	Controller					controller;

	SolverFactory				sfac			= new SolverFactory(dirsolveur);
	PreProcessorFactory			pfac			= new PreProcessorFactory(dirpreproc);

	CNFUse						defaultCNFUse;

	Semaphore					sem;

	private CNFUse getCNFUse(String path) {
		CNFUse cnfuse;
		CNF cnf;

		try
		{
			cnf = new FileCNF(path);
		} catch (IOException e)
		{
			e.printStackTrace();
			return null;
		}

		cnfuse = new CNFUse(cnf);
		return cnfuse;
	}

	/**
	 * reinitialize the global attribute
	 */
	private void newSet() {
		sem = new Semaphore(0);
		ig = new IG(sem);
		controller = new Controller(ig);
		ig.setController(controller);
		defaultCNFUse = getCNFUse(cnfcourpath);
	}

	@Before
	public void setUp() {
		newSet();
	}

	@Test
	public void testOpenSessionWithWrongCNF() {

		System.out.println("\n\nTEST : testOpenSessionWithWrongCNF\n");

		IG ig = new IG(sem) {

		};

		controller = new Controller(ig);
		ig.setController(controller);

		controller.openSession("./preproc");

		assertEquals("doesn't show popup", ig.popups.size(), 1);
		assertTrue("open cnf that doesn't exist", ig.igsession.isEmpty());
	}

	@Test
	public void testOpenSessionWithProblemIG() {

		System.out.println("\n\nTEST : testOpenSessionWithProblemIG\n");

		IG ig = new IG(sem) {
			@Override
			public IIGSessionManager openSession(CNFUse cnf, ISessionManager manager) {
				return null;
			}
		};

		controller = new Controller(ig);
		ig.setController(controller);

		controller.openSession(cnfcourpath);

		assertEquals("doesn't show popup", ig.popups.size(), 1);
		assertTrue("open cnf that doesn't exist", ig.igsession.isEmpty());

	}

	@Test
	public void testOpenSession() {
		System.out.println("\n\nTEST : testOpenSession\n");

		IG ig = new IG(sem) {

		};

		controller = new Controller(ig);
		ig.setController(controller);

		controller.openSession(cnfcourpath);

		assertTrue("detect problem", ig.popups.isEmpty());
		assertEquals("doesn't open correctly the cnf in ig", ig.igsession.size(), 1);

		CNFUse cnf = (CNFUse) ig.igsession.values().toArray()[0];
		assertEquals("wrong cnf store", cnf.getCnf().getCNFfile().getPath(), cnfcourpath);

		// TestIGSessionManager igsession = (TestIGSessionManager)
		// ig.igsession.keySet().toArray()[0];

	}

	@Test
	public void testChangeDirectory() {
		File errordir = new File("./tstcnf/cour.cnf");
		assertFalse("change directory with a file that is not a directory ", controller.changeDefaultCNFDirectory(errordir));
		assertFalse("change directory with a file that is not a directory ", controller.changePreProcessorDirectory(errordir));
		assertFalse("change directory with a file that is not a directory ", controller.changeSolverDirectory(errordir));
	}

	private class IG implements IIG {
		public IController							ctrl		= null;
		public List<EErrorPopUp>					popups		= new ArrayList<EErrorPopUp>();
		public Map<TestIGSessionManager, CNFUse>	igsession	= new HashMap<TestIGSessionManager, CNFUse>();
		public Semaphore							sem;

		public IG(Semaphore sem) {
			this.sem = sem;
		}

		@Override
		public void closeSession(ISessionManager session) {
			System.out.println("close " + session);
			TestIGSessionManager tmp = null;
			for (TestIGSessionManager i : igsession.keySet())
				if (i.manager == session)
				{
					tmp = i;
					break;
				}
			if (tmp != null)
				igsession.remove(tmp);

		}

		@Override
		public IIGSessionManager openSession(CNFUse cnf, ISessionManager manager) {
			TestIGSessionManager tmp = new TestIGSessionManager(sem);
			igsession.put(tmp, cnf);
			return tmp;
		}

		@Override
		public void showErrorPopup(EErrorPopUp type, String message) {
			popups.add(type);
		}

		public void setController(IController ctrl) {
			this.ctrl = ctrl;
		}

		@Override
		public IController getController() {
			// TODO Auto-generated method stub
			return null;
		}

		@Override
		public boolean yesNoQuestionPopup(String question) {
			// TODO Auto-generated method stub
			return false;
		}


	}


	private class TestIGSessionManager implements IIGSessionManager {

		public List<EErrorPopUp>	popups		= new ArrayList<EErrorPopUp>();
		public List<SessionBlock>	running		= new ArrayList<SessionBlock>();
		public ISessionManager		manager		= null;
		public List<CNFUse>			showall		= new ArrayList<CNFUse>();
		public List<CNFUse>			updateinfo	= new ArrayList<CNFUse>();
		public List<CNFUse>			update		= new ArrayList<CNFUse>();
		public Semaphore			attend;

		public void setAttend(Semaphore sem) {
			attend = sem;
		}

		public TestIGSessionManager(Semaphore sem) {
			attend = sem;
		}

		@Override
		public void addRunningExecution(ExecutableSessionBlock exec, CNFUse mere) {
			running.add(exec);
		}

		@Override
		public void removeRunningExecution(ExecutableSessionBlock exec, CNFUse mere) {
			running.remove(exec);
		}


		public void setSessionManager(ISessionManager sessionManager) {
			manager = sessionManager;
		}


		@Override
		public void showErrorPopup(EErrorPopUp type, String message) {
			popups.add(type);
		}

		@Override
		public void updateCNFInformation(CNFUse cnf) {
			updateinfo.add(cnf);
		}

		@Override
		public void updateCNFUse(CNFUse cnf) {
			update.add(cnf);
		}

		@Override
		public ISessionManager getSessionManager() {
			return manager;
		}

	}
}
